package org.sdnstproject.interlayer.interlayerProxy;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.concurrent.LinkedBlockingDeque;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;

public class SwitchToInterlayer implements Runnable {
	private static final Logger log = LoggerFactory.getLogger(SwitchToInterlayer.class);
	private Socket socket;
    private InputStream in;
    private OutputStream out;
    private InterlayerToController other;

	public LinkedBlockingDeque<ByteBuf> msgQueue;
    public volatile boolean running = true;
    public volatile boolean isReady = false;
    
    public SwitchToInterlayer(Socket socket) {
    	this.socket = socket;
    	this.msgQueue = new LinkedBlockingDeque<>();
    }
    
    public InterlayerToController getOther() {
    	return other;
    }
    
    public void setOther(InterlayerToController other) {
    	this.other = other;
    }
    public void sendRawMsg(ByteBuf buf) {
        int length = buf.readableBytes();
        byte[] bytes = new byte[length];
        buf.getBytes(buf.readerIndex(), bytes);

        try {
            this.out.write(bytes, 0, length);
        } catch (IOException e) {
            e.printStackTrace();
        }

        buf.clear();
        buf.release();
    }
    
	@Override
	public void run() {
		System.out.println("SwitchToInterlayer run...");
		try {
			in = socket.getInputStream();
			out = socket.getOutputStream();
		} catch (IOException e2) {
			e2.printStackTrace();
		}
		byte[] recv;
        int readlen;
        try {
            while (running && !Thread.currentThread().isInterrupted()) {
                recv = new byte[8192];
                int mlen;
                int len = 0;
                if ((readlen = in.read(recv, 0, recv.length)) != -1) {
                    byte[] lenarr = {recv[2], recv[3]};
                    mlen = Integer.parseInt(javax.xml.bind.DatatypeConverter.printHexBinary(lenarr), 16);
                    ByteBuf newrecv = Unpooled.directBuffer(mlen);
                    newrecv.writeBytes(recv);
                    len = len + readlen;
                    newrecv.writerIndex(len);

                    while(mlen > len){
                        if((readlen = in.read(recv, 0, recv.length)) != -1){
                            newrecv.writeBytes(recv);
                            len = len + readlen;
                            newrecv.writerIndex(len);
                        }
                    }
//                    int length = newrecv.readableBytes();
//                    byte[] bytes = new byte[length];
//                    newrecv.getBytes(newrecv.readerIndex(), bytes);
//                    msgQueue.add(newrecv);
                    this.other.sendRawMsg(newrecv);
                } else {
                    in.close();
                    out.close();
                    socket.close();
                    break; 
                }
            }
        } catch (Exception e) {
        	Thread.currentThread().interrupt();
            e.printStackTrace();
        } finally {
        	try {
                if (in != null)
                    in.close();
                if (out != null)
                    out.close();
                if (socket != null)
                    socket.close();
            } catch (IOException e1) {
                e1.printStackTrace();
            }

        }
	}

}
